﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;

using Spring.Template.Velocity;
using Spring.Template.Velocity.Config;

using NVelocity;
using NVelocity.App;

using Yawf.Core.Exceptions;
using Yawf.Core.Logs;
using Yawf.Security.Entities;
using Yawf.Web.Managers.Entities;
using Yawf.Web.Utils;

namespace Yawf.Web.Managers {
	public class NVelocityViewManager : IModelViewerManager{
		// Fields
		private VelocityEngine engine;

		// Properties
		public VelocityEngine Engine { get { return engine; } set { engine = value; } }

		/// <summary>
		/// This ModelViewManager just uses NvelocityTemplate as Template engine
		/// </summary>
		/// <param name="requestWrapper">RequestWrapper</param>
		/// <param name="responseWrapper">ResponseWrapper</param>
		/// <param name="view">View object</param>
		/// <param name="user">Current User</param>
		public void ProcessView(RequestWrapper requestWrapper,ResponseWrapper responseWrapper,View view,IUser user) {
			Hashtable model;
			VelocityContext context;

			try {
				// Get Model
				model = CreateModel(requestWrapper, responseWrapper,user);
				context = new VelocityContext(model);

				// Output view
				engine.MergeTemplate(view.Resource, view.Encoding, context, responseWrapper.Writer);
			} catch (Exception e) {
				Log.ExceptionMessage(this.GetType(),"Error reading template " + view.Resource,e);
				throw new YawfException("Error reading template " + view.Resource,e);
			}
		}									// ProcessView

		/// <summary>
		/// Returns a Hashtable with all request data found
		/// </summary>
		/// <param name="requestWrapper">RequestWrapper to take request data from</param>
		/// <returns>A Hashtable</returns>
		private Dictionary<String,String> GetRequestMap(RequestWrapper requestWrapper) {
			Dictionary<String,String> requestMap;
			IList<String> paramNames;
			String name;
			int i;

			requestMap = new Dictionary<String,String>();
			paramNames = requestWrapper.GetParameterNames();
			for (i = 0; paramNames != null && i < paramNames.Count; i++) {
				name = paramNames[i];
				if (name != null) {
					requestMap.Add(name, requestWrapper.GetString(name, ""));
				}
			}

			return requestMap;
		}								// GetRequestMap

		/// <summary>
		/// Gets model data found in responseWrapper as a HashTable
		/// </summary>
		/// <param name="template">StringTemplate to use</param>
		/// <param name="requestWrapper">RequestWrapper object</param>
		/// <param name="responseWrapper">ResponseWrapper object</param>
		private Hashtable CreateModel(RequestWrapper requestWrapper, ResponseWrapper responseWrapper, IUser user) {
			IList<Object> objects;
			IList<String> objectNames;
			Hashtable model;
			Object obj;
			String tagName;
			int i;

			// Add some useful data to ResponseWrapper before we build Hashtable with model
			responseWrapper.Add(requestWrapper.GetServerName(), "http_host");
			responseWrapper.Add(requestWrapper.GetContextPath(), "module_name");
			if (user != null) {
				responseWrapper.Add(user, "current_user");
			}
			responseWrapper.Add(DateTime.Now, "current_date");

			// Add request data
			model = new Hashtable();
			model.Add("request", GetRequestMap(requestWrapper));

			// Get all objects and object names in collector
			objects = responseWrapper.ResultObjects;
			objectNames = responseWrapper.ResultNames;

			// Loop through all object and serialize the into the xml document
			for (i = 0; objectNames.Count == objects.Count && objects != null && i < objects.Count; i++) {
				obj = objects[i];
				tagName = objectNames[i];
				if (tagName == null || tagName.Trim() == "") {
					tagName = "object_" + i;
				}

				// Add to template 
				if (!model.ContainsKey(tagName)) {
					model.Add(tagName, obj);
				} else {
					model[tagName] = obj;
				}

				
			}

			return model;
		}								// CreateModel
	}								// Class
}
